package com.sixbro.file.storage.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.sixbro.file.storage.entity.FileDocument;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * <p>
 * 七牛云上传Service
 * </p>
 *
 * @Author: Mr.Lu
 * @Since: 2020/6/23 14:12
 */
@Slf4j
@Service
public class QiNiuFileStorageServiceImpl extends AbstractFileStorageService implements InitializingBean {
    private final UploadManager uploadManager;

    private final Auth auth;

    @Value("${qiniu.bucket}")
    private String bucket;

    private StringMap putPolicy;

    @Value("${spring.servlet.multipart.location}")
    private String fileTempPath;

    @Value("${qiniu.prefix}")
    private String prefix;

    @Autowired
    public QiNiuFileStorageServiceImpl(UploadManager uploadManager, Auth auth) {
        this.uploadManager = uploadManager;
        this.auth = auth;
    }

    /**
     * 七牛云上传文件
     *
     * @param file 文件
     * @return 七牛上传Response
     * @throws QiniuException 七牛异常
     */
    @Override
    protected void uploadHandler(FileDocument document, MultipartFile file) throws IOException {
        String rawFileName = StrUtil.subBefore(document.getOriginalFilename(), ".", true);
        String localFilePath = StrUtil.appendIfMissing(fileTempPath, "/") + rawFileName + "-" + DateUtil.current(false) + "." + document.getFiletype();

        Response response = this.uploadManager.put(file.getBytes(), localFilePath, getUploadToken());
        if (response.isOK()) {
            int retry = 0;
            while (response.needRetry() && retry < 3) {
                response = this.uploadManager.put(file.getBytes(), file.getName(), getUploadToken());
                retry++;
            }
            JSONObject jsonObject = JSONUtil.parseObj(response.bodyString());
            String yunFileName = jsonObject.getStr("key");
            String yunFilePath = StrUtil.appendIfMissing(prefix, "/") + yunFileName;

            log.info("【文件上传至七牛云】绝对路径：{}", yunFilePath);
        } else {
            log.error("【文件上传至七牛云】失败，{}", JSONUtil.toJsonStr(response));
        }

    }

    @Override
    public void afterPropertiesSet() {
        this.putPolicy = new StringMap();
        putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}");
    }

    /**
     * 获取上传凭证
     *
     * @return 上传凭证
     */
    private String getUploadToken() {
        return this.auth.uploadToken(bucket, null, 3600, putPolicy);
    }
}
